const express = require("express");
const router = express.Router();
const { resData } = require("../../utils/format");
const { createRandomNumCode } = require("../../utils/create");
const multer = require("multer");
const jwt = require("jsonwebtoken");
const UserModel = require("../../models/User");
const CheckCodeModel = require("../../models/CheckCode");
const middleware_auth = require("../../middleware/auth");
const assert = require("http-assert");
const bcrypt = require("bcrypt");
const { sendEmailCode } = require("../../utils/send");
module.exports = app => {
    /**
     * @apiGroup 通用
     * @api {post} /common/api/login 登录
     * @apiParam  {String} username 用户名
     * @apiParam  {String} password 密码
     */
    router.post("/login", async (req, res) => {
        console.log({ originnalUrl: req.originalUrl, method: req.method });
        const { username, password } = req.body;
        assert(username, 422, "请输入用户名");
        assert(password, 422, "请输入密码");
        const user = (await UserModel.findOne({ username: username })) || (await UserModel.findOne({ email: username }));
        assert(user, 422, "用户名不存在");
        assert(bcrypt.compareSync(password, user.password), 422, "密码错误"); //第一个：明文，第二个：密文
        const token = jwt.sign({ id: user._id, exp: Math.floor(Date.now() / 1000) + app.get("jwtExp") }, app.get("jwtSecret"));
        res.send(resData({ user, token }, { message: "登陆成功" }));
    });
    /**
     * @apiGroup 通用
     * @api {post} /common/api/logout 退出登录
     */
    router.post("/logout", async (req, res) => {
        req.session.destroy();
        res.send(resData(null));
    });
    /**
     * @apiGroup 通用
     * @api {post} /common/api/sendEmailCode 发邮件验证码(登录)
     * @apiParam  {String} email 邮箱
     */
    router.post("/sendEmailCode", async (req, res) => {
        const { email } = req.body;
        const findUser = await UserModel.findOne({ email });
        if (!findUser) {
            return res.send(resData(null, { code: 401, message: "用户不存在" }));
        }
        const findCode = await CheckCodeModel.findOne({ email });
        let checkCodeObj = null;
        let emailCheckCode = "000000";
        //发送过验证码
        if (findCode && findCode.type == "login") {
            const { updateTime } = findCode;
            //发送间隔小于1分钟
            assert(Date.now() - new Date(updateTime).getTime() >= 1000 * 60, 403, "请稍后再点发送");
            emailCheckCode = createRandomNumCode(6);
            sendEmailCode({ to: email, html: emailCheckCode }).catch(err => {
                return res.send(resData(err, { message: "发送失败", code: "500" }));
            });
            await CheckCodeModel.findByIdAndUpdate(findCode._id, {
                code: emailCheckCode,
                email,
                expiredTime: Date.now() + 1000 * 60 * 5,
            });
            checkCodeObj = await CheckCodeModel.findOne({ email });
        } else {
            emailCheckCode = createRandomNumCode(6);
            sendEmailCode({ to: email, html: emailCheckCode }).catch(err => {
                return res.send(resData(err, { message: "发送失败", code: "500" }));
            });
            checkCodeObj = await CheckCodeModel.create({ code: emailCheckCode, email, expiredTime: Date.now() + 1000 * 60 * 5, type: "login" });
        }
        res.send(resData(checkCodeObj.code, { message: "发送成功" }));
    });
    /**
     * @apiGroup 通用
     * @api {post} /common/api/loginByEmailCode 邮件验证码登录
     * @apiParam  {String} email 邮箱
     * @apiParam  {String} code 验证码
     */
    router.post("/loginByEmailCode", async (req, res) => {
        const { email, code } = req.body;
        const findUser = await UserModel.findOne({ email });
        assert(findUser, 401, "用户不存在");
        const findCode = await CheckCodeModel.findOne({ email });
        assert(findCode, 401, "请先发送验证码");
        assert(findCode.type == "login", 401, "请先发送验证码");
        assert(code == findCode.code, 401, "验证码错误");
        assert(findCode.expiredTime >= Date.now(), 401, "验证码已过期");
        // console.log(`距离验证码过期还有${(findCode.expiredTime-Date.now())/1000}秒`);
        const token = jwt.sign({ id: findUser._id, exp: Math.floor(Date.now() / 1000) + app.get("jwtExp") }, app.get("jwtSecret"));
        res.send(resData({ user: findUser, token }, { message: "登录成功" }));
    });
    /**
     * @apiGroup 通用
     * @api {post} /common/api/register 注册账号
     * @apiParam  {String} username 用户名
     * @apiParam  {String} email 邮箱
     * @apiParam  {String} password 密码
     * @apiParam  {String} role 角色
     */
    router.post("/register", async (req, res) => {
        const { username, password, role, email } = req.body;
        assert(username, 400, "请输入username");
        req.body.username = String(username);
        assert(email, 400, "请输入email");
        req.body.email = String(email);
        assert(password, 400, "请输入password");
        req.body.password = String(password);
        assert(role, 400, "请输入role");
        const UserByUsername = await UserModel.findOne({ username });
        UserByUsername ? assert(false, 401, "用户名已存在") : false;
        const UserByEmail = await UserModel.findOne({ email });
        UserByEmail ? assert(false, 401, "邮箱已存在") : false;
        const data = await UserModel.create(req.body);
        res.send(resData(data, { message: "注册成功" }));
    });
    //文件上传配置
    const upload = multer({
        storage: multer.diskStorage({
            //存储文件的位置
            destination: (req, file, cb) => {
                cb(null, __dirname + "/../../uploads");
            },
            //存储文件的名称
            filename: (req, file, cb) => {
                // let file = {fieldname:'file',originalname:'3d3428432ca6b140f5e48df9dec7187a.jpg',encoding:'7bit',mimetype:'image/jpeg'};
                cb(null, file.originalname);
            },
        }),
    });
    /**
     * @apiGroup 通用
     * @api {post} /common/api/upload 文件上传服务
     * @apiParam  {formData} file 文件对象
     */
    router.post("/upload", middleware_auth(), upload.single("file"), (req, res) => {
        const file = req.file;
        res.send(file);
    });
    app.use(
        "/common/api",
        async (req, res, next) => {
            console.log({ originnalUrl: req.originalUrl, method: req.method });
            next();
        },
        router
    );
};
